package com.sunchangpeng.wechat.mp.oauth2;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.sunchangpeng.wechat.core.WechatClient;
import com.sunchangpeng.wechat.core.utils.URLUtils;
import com.sunchangpeng.wechat.mp.EndpointProvider;
import com.sunchangpeng.wechat.mp.MpAppSetting;
import com.sunchangpeng.wechat.mp.MpWechatClientFactory;
import com.sunchangpeng.wechat.mp.user.bean.Gender;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

public class OAuth2s {
    private WechatClient wechatClient;

    public void setWechatClient(WechatClient wechatClient) {
        this.wechatClient = wechatClient;
    }

    public static OAuth2s with(MpAppSetting appSetting) {
        OAuth2s oAuth2s = new OAuth2s();
        oAuth2s.setWechatClient(MpWechatClientFactory.getInstance().with(appSetting));
        return oAuth2s;
    }

    /**
     * 生成授权链接
     */
    public String authenticationUrl(String redirect, String scope) {
        return authenticationUrl(redirect, scope, null);
    }

    /**
     * 生成授权链接
     */
    public String authenticationUrl(String redirect, String scope, String state) {
        if (StringUtils.isBlank(state)) {
            String url = EndpointProvider.get("url.oauth.authentication");
            return String.format(url, wechatClient.getAppId(), URLUtils.encode(redirect), scope);
        } else {
            String url = EndpointProvider.get("url.oauth.authentication.state");
            return String.format(url, wechatClient.getAppId(), URLUtils.encode(redirect), scope, state);
        }
    }

    /**
     * 获取access token
     */
    public AccessToken getAccessToken(String code) {
        String url = EndpointProvider.get("url.oauth.accesstoken.get");
        String formatUrl = String.format(url, wechatClient.getAppId(), wechatClient.getSecret(), code);
        String response = wechatClient.getText(formatUrl);
        return JSON.parseObject(response, AccessToken.class);
    }

    /**
     * 刷新access token
     */
    public AccessToken refreshToken(String refreshToken) {
        String url = EndpointProvider.get("url.oauth.accesstoken.refresh");
        String formatUrl = String.format(url, wechatClient.getAppId(), refreshToken);
        String response = wechatClient.getText(formatUrl);
        return JSON.parseObject(response, AccessToken.class);
    }

    /**
     * 获取用户信息
     */
    public OpenUser userInfo(String accessToken, String openId) {
        return userInfo(accessToken, openId, "zh_CN");
    }

    /**
     * 获取用户信息
     */
    public OpenUser userInfo(String accessToken, String openId, String lang) {
        String url = EndpointProvider.get("url.oauth.userinfo.get");
        String formatUrl = String.format(url, accessToken, openId, lang);
        String response = wechatClient.getText(formatUrl);
        return JSON.parseObject(response, OpenUser.class);
    }
    /**
     * 检验授权凭证（access_token）是否有效
     */
    public void validToken(String accessToken, String openId) {
        String url = EndpointProvider.get("url.oauth.accesstoken.valid");
        String formatUrl = String.format(url, accessToken, openId);
        wechatClient.getText(formatUrl);
    }

    @Data
    public class AccessToken {
        @JSONField(name = "access_token")
        private String accessToken;

        @JSONField(name = "refresh_token")
        private String refreshToken;

        @JSONField(name = "openid")
        private String openId;

        @JSONField(name = "unionid")
        private String unionId;

        private String scope;

        @JSONField(name = "expires_in")
        private int expiresIn;

        private long expiresTill;

        public void setExpiresIn(int expiresIn) {
            this.expiresIn = expiresIn;
            this.expiresTill = System.currentTimeMillis() + (expiresIn * 1000) - 300000;
        }
    }

    @Data
    public class OpenUser {
        @JSONField(name = "openid")
        private String openId;

        @JSONField(name = "nickname")
        private String nickName;

        private Gender sex;

        private String province;
        private String city;
        private String country;

        @JSONField(name = "headimgurl")
        private String headImgUrl;

        @JSONField(name = "unionid")
        private String unionId;

        private String[] privilege;
    }
}
